package cn.shop.utils;


import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;

import java.lang.reflect.Method;

/**
 * @author : 李一涵
 * @date : Created in 2021-11-10 17:22
 * @description :
 */
@SuppressWarnings("unchecked")
public class EnumConverter implements ConverterFactory<String, Enum<?>> {

    @Override
    public <T extends Enum<?>> Converter<String, T> getConverter(Class<T> targetType) {
        return new StringToEnum<>(targetType);
    }

    private class StringToEnum<T extends Enum> implements Converter<String, T> {

        private final Class<T> enumType;

        public StringToEnum(Class<T> enumType) {
            this.enumType = enumType;
        }

        @Override
        public T convert(String source) {
            if (source.length() == 0) {
                return null;
            }
            try { //先通过name获取枚举
                return (T) Enum.valueOf(enumType, source);
            } catch (Exception e) { //再通过其他enum值进行获取
                for (Enum<?> enumConstant : enumType.getEnumConstants()) {
                    for (Method method1 : enumConstant.getClass().getDeclaredMethods()) {
                        method1.setAccessible(true);
                        if (method1.getParameterCount() == 0) {
                            try {
                                Object v = method1.invoke(enumConstant);
                                if (v instanceof Integer) {
                                    if (source.matches("^\\d+$")) {
                                        if (Integer.valueOf(source).equals(v)) {
                                            return (T) Enum.valueOf(enumType, enumConstant.name());
                                        }
                                    }
                                } else if (v instanceof String) {
                                    if (source.equals(v)) {
                                        return (T) Enum.valueOf(enumType, enumConstant.name());
                                    }
                                }
                            } catch (Exception e1) {
                                e1.printStackTrace();
                            }
                        }
                    }
                }
            }
            return null;
        }
    }
}
